Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bitmap support #127

Merged
merged 116 commits into from
Oct 31, 2024
Merged

Bitmap support #127

merged 116 commits into from
Oct 31, 2024

Conversation

tomlm
Copy link
Collaborator

@tomlm tomlm commented Oct 31, 2024

  • Image tags work
  • Scale works

Images

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced a GalleryImage user control for displaying images in a visually appealing gallery layout with scrolling capabilities.
    • Enhanced bitmap handling with new methods for loading and resizing images, improving overall functionality.
    • Added ConsoleBrush class for improved brush management with color and pixel background options.
    • New package dependencies to enhance graphics rendering capabilities.
  • Bug Fixes

    • Implemented previously unimplemented methods for bitmap loading and drawing, enhancing user experience.
  • Documentation

    • Updated project files to include new resources and dependencies, enhancing graphics rendering capabilities.

jinek added 30 commits April 14, 2024 01:02
Overhauled various files through code refactoring, removing unnecessary attributes, updating type definitions, cleaning up method signatures. Significant changes were made to the Core/Infrastructure platform and several TurboVision themes and templates.
This commit transitions helper methods to use a new syntax, and adjusts various bindings in grid items and data templates. In several instances, template-related properties such as design width and height were removed. Changes were also made to focus management, specifically transitioning from using the deprecated FocusManager.Instance to using AvaloniaLocator for service retrieval. The GlyphRun creation was refactored in SymbolsControl.cs.
Introduced Avalonia threading in ConsoloniaPlatform, and bound to a new ManagedDispatcherImpl. Moreover, text shaping has been improved in SymbolsControl by replacing the default measure with an enumerable list of GlyphInfo. Some code has been commented out in ApplicationStartup for later consideration.
Removed dependency on IPlatformRenderInterface in several methods of ConsoloniaRenderInterface and adjusted corresponding logic. Improved DrawGlyphRun method's implementation in DrawingContextImpl, modifying glyphRun checks and string drawing. Made small adjustments to classes MoveConsoleCaretToPositionBrush and FourBitColorBrush for better alignment with IImmutableBrush.
The transform in the DrawingContextImpl.cs was updated to be initialized with Matrix identity. Removed the unused methods related to geometry and rendering in ConsoloniaRenderInterface.cs. Made a small adjustment to exception message in RenderTarget.cs for clarity.
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 13

🧹 Outside diff range and nitpick comments (7)
src/Consolonia.Core/Drawing/BitmapImpl.cs (2)

42-42: Document the height scaling factor

The height scaling factor of 0.55 in PixelSize seems arbitrary. Consider adding a documentation comment explaining why this specific scaling factor is used and its implications.


40-40: Consider making DPI configurable

The DPI value is hardcoded to 96, which might not be suitable for all display scenarios. Consider making this configurable or retrieving it from the system settings.

src/Consolonia.Core/Drawing/ConsoloniaRenderInterface.cs (1)

54-54: Remove Unnecessary Commented-Out Code

The commented-out line at 54 is unnecessary and can be removed to improve code readability.

Apply this diff to remove the commented code:

-// return new ConsoleRenderTargetBitmapImpl(size, dpi);
src/Consolonia.Core/Drawing/DrawingContextImpl.cs (4)

141-153: Improve code readability by formatting nested loops and blocks

The nested for loops starting at line 141 lack proper indentation, which affects code readability and maintainability.

Ensure that all code blocks are properly indented to enhance clarity:

for (int x = 0; x < width; x++)
{
    for (int y = 0; y < height; y++)
    {
        // Code inside inner loop
    }
}
🧰 Tools
🪛 GitHub Check: build

[notice] 151-151:
"[ConvertToLambdaExpression] Use lambda expression" on /home/runner/work/Consolonia/Consolonia/src/Consolonia.Core/Drawing/DrawingContextImpl.cs(151,46)


Line range hint 270-289: Handle unexpected Brush types in ExtractColorOrNullWithPlatformCheck

The method assumes that pen.Brush is of specific types. If an unexpected Brush type is passed, it may result in an exception or unintended behavior.

Consider adding a default case or throwing a more descriptive exception to handle unexpected Brush types:

switch (pen.Brush)
{
    case LineBrush lineBrush:
        lineStyle = lineBrush.LineStyle;
        break;
    case ConsoleBrush consoleBrush:
        // Existing handling
        break;
    case ImmutableSolidColorBrush solidColorBrush:
        // Existing handling
        break;
    default:
        throw new NotSupportedException($"Brush type '{pen.Brush.GetType()}' is not supported.");
}

Line range hint 360-378: Make tabSize a configurable constant

In the DrawStringInternal method, tabSize is hardcoded to 8. For better flexibility and maintainability, define tabSize as a constant or make it configurable.

Apply this diff to define tabSize as a private constant:

+private const int TabSize = 8;

...

case '\t':
{
-    const int tabSize = 8;
     var consolePixel = new Pixel(' ', foregroundColor);
-    for (int j = 0; j < tabSize; j++)
+    for (int j = 0; j < TabSize; j++)
     {
         Point newCharacterPoint = characterPoint.WithX(characterPoint.X + j);
         CurrentClip.ExecuteWithClipping(newCharacterPoint, () =>
         {
             _pixelBuffer.Set((PixelBufferCoordinate)newCharacterPoint,
                 (oldPixel, cp) => oldPixel.Blend(cp), consolePixel);
         });
     }

-    currentXPosition += tabSize - 1;
+    currentXPosition += TabSize - 1;
}

151-151: Simplify lambda expression using method group

Static analysis suggests converting the lambda expression to a method group for simplicity.

Apply this diff to simplify the lambda expression:

_pixelBuffer.Set(new PixelBufferCoordinate((ushort)localPx, (ushort)localPy),
-    (existingPixel, _) => existingPixel.Blend(imagePixel), imagePixel.Background.Color);
+    existingPixel => existingPixel.Blend(imagePixel), imagePixel.Background.Color);
🧰 Tools
🪛 GitHub Check: build

[notice] 151-151:
"[ConvertToLambdaExpression] Use lambda expression" on /home/runner/work/Consolonia/Consolonia/src/Consolonia.Core/Drawing/DrawingContextImpl.cs(151,46)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between eac7395 and 8fa9eb0.

📒 Files selected for processing (4)
  • src/Consolonia.Core/Drawing/BitmapImpl.cs (1 hunks)
  • src/Consolonia.Core/Drawing/ConsoleBrush.cs (1 hunks)
  • src/Consolonia.Core/Drawing/ConsoloniaRenderInterface.cs (2 hunks)
  • src/Consolonia.Core/Drawing/DrawingContextImpl.cs (10 hunks)
🧰 Additional context used
🪛 GitHub Check: build
src/Consolonia.Core/Drawing/BitmapImpl.cs

[notice] 96-96:
"[ConvertSwitchStatementToSwitchExpression] Convert 'switch' statement to 'switch' expression" on /home/runner/work/Consolonia/Consolonia/src/Consolonia.Core/Drawing/BitmapImpl.cs(96,13)


[notice] 68-68:
"[ConvertToConstant.Local] Convert into constant" on /home/runner/work/Consolonia/Consolonia/src/Consolonia.Core/Drawing/BitmapImpl.cs(68,17)


[notice] 27-27:
"[ConvertToUsingDeclaration] Convert into 'using' declaration" on /home/runner/work/Consolonia/Consolonia/src/Consolonia.Core/Drawing/BitmapImpl.cs(27,13)


[notice] 58-58:
"[ConvertToUsingDeclaration] Convert into 'using' declaration" on /home/runner/work/Consolonia/Consolonia/src/Consolonia.Core/Drawing/BitmapImpl.cs(58,13)


[notice] 69-69:
"[ConvertToUsingDeclaration] Convert into 'using' declaration" on /home/runner/work/Consolonia/Consolonia/src/Consolonia.Core/Drawing/BitmapImpl.cs(69,13)

src/Consolonia.Core/Drawing/ConsoleBrush.cs

[notice] 186-186:
"[ConvertIfStatementToSwitchStatement] Convert 'if' statement into 'switch' statement" on /home/runner/work/Consolonia/Consolonia/src/Consolonia.Core/Drawing/ConsoleBrush.cs(186,13)

src/Consolonia.Core/Drawing/ConsoloniaRenderInterface.cs

[notice] 65-65:
"[ConvertToUsingDeclaration] Convert into 'using' declaration" on /home/runner/work/Consolonia/Consolonia/src/Consolonia.Core/Drawing/ConsoloniaRenderInterface.cs(65,13)


[notice] 79-79:
"[ConvertToUsingDeclaration] Convert into 'using' declaration" on /home/runner/work/Consolonia/Consolonia/src/Consolonia.Core/Drawing/ConsoloniaRenderInterface.cs(79,13)

src/Consolonia.Core/Drawing/DrawingContextImpl.cs

[notice] 151-151:
"[ConvertToLambdaExpression] Use lambda expression" on /home/runner/work/Consolonia/Consolonia/src/Consolonia.Core/Drawing/DrawingContextImpl.cs(151,46)

🔇 Additional comments (1)
src/Consolonia.Core/Drawing/DrawingContextImpl.cs (1)

188-188: Verify correct character mapping in DrawGlyphRun

Converting glyphRunImpl.GlyphIndices directly to characters may not always result in valid Unicode characters, especially with complex fonts or glyph indices that do not correspond to standard Unicode code points.

Consider verifying that glyph indices accurately represent the intended characters, and handle cases where direct casting may not be appropriate.

src/Consolonia.Core/Drawing/BitmapImpl.cs Outdated Show resolved Hide resolved
src/Consolonia.Core/Drawing/BitmapImpl.cs Outdated Show resolved Hide resolved
src/Consolonia.Core/Drawing/DrawingContextImpl.cs Outdated Show resolved Hide resolved
src/Consolonia.Core/Drawing/ConsoleBrush.cs Outdated Show resolved Hide resolved
src/Consolonia.Core/Drawing/ConsoleBrush.cs Outdated Show resolved Hide resolved
@jinek jinek linked an issue Oct 31, 2024 that may be closed by this pull request
@tomlm tomlm enabled auto-merge (squash) October 31, 2024 17:01
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Outside diff range and nitpick comments (1)
src/Consolonia.Core/Drawing/DrawingContextImpl.cs (1)

51-58: Ensure proper memory management with SkiaSharp resources

The bitmap drawing implementation should dispose of all SkiaSharp resources properly. While using statements are correctly applied for bitmap and canvas, consider wrapping the entire operation in a try-finally block to ensure cleanup in case of exceptions.

Apply this diff:

 public void DrawBitmap(IBitmapImpl source, double opacity, Rect sourceRect, Rect destRect)
 {
+    try
+    {
         var targetRect = new Rect(Transform.Transform(new Point(destRect.TopLeft.X, destRect.TopLeft.Y)),
             Transform.Transform(new Point(destRect.BottomRight.X, destRect.BottomRight.Y)));
         var bmp = (BitmapImpl)source;
         using var bitmap = new SKBitmap((int)targetRect.Width, (int)targetRect.Height);
         using var canvas = new SKCanvas(bitmap);
         canvas.DrawBitmap(bmp.Bitmap, new SKRect(0, 0, (float)targetRect.Width, (float)targetRect.Height), 
             new SKPaint { FilterQuality = SKFilterQuality.Medium });
+    }
+    finally
+    {
+        // Ensure any additional resources are cleaned up
+    }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 8fa9eb0 and 6f3a4c7.

📒 Files selected for processing (4)
  • src/Consolonia.Core/Drawing/BitmapImpl.cs (1 hunks)
  • src/Consolonia.Core/Drawing/DrawingContextImpl.cs (4 hunks)
  • src/Consolonia.Core/Text/GlyphRunImpl.cs (1 hunks)
  • src/Consolonia.Gallery/Consolonia.Gallery.csproj (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/Consolonia.Core/Text/GlyphRunImpl.cs
  • src/Consolonia.Gallery/Consolonia.Gallery.csproj
🔇 Additional comments (4)
src/Consolonia.Core/Drawing/DrawingContextImpl.cs (3)

12-12: LGTM: SkiaSharp integration

The addition of SkiaSharp for bitmap support is appropriate and aligns with the PR objectives.


59-59: Uncomment and implement proper clipping

The commented out clipping intersection suggests incomplete implementation. Consider implementing proper clipping to ensure bitmap drawing respects clip bounds.

Let's verify if clipping is implemented elsewhere:

#!/bin/bash
# Search for clipping implementations in the codebase
rg -l "Intersect.*clip" --type cs

366-366: Verify transform handling in string drawing

The commented out transform check suggests that non-translate transforms might not be properly handled. This could lead to incorrect text rendering with rotated or scaled transforms.

Let's check for transform usage in the codebase:

src/Consolonia.Core/Drawing/BitmapImpl.cs (1)

41-41: Verify the scaling factor in PixelSize calculation

The PixelSize property uses new(Bitmap.Width, (int)(Bitmap.Height * .55)), which multiplies the height by 0.55. Please confirm that this scaling is intentional and necessary for the correct display of the bitmap.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 6f3a4c7 and e05d357.

📒 Files selected for processing (2)
  • src/Consolonia.Core/Drawing/BitmapImpl.cs (1 hunks)
  • src/Consolonia.Core/Drawing/DrawingContextImpl.cs (4 hunks)
🧰 Additional context used
🪛 GitHub Check: build
src/Consolonia.Core/Drawing/BitmapImpl.cs

[notice] 85-85:
"[ConvertIfStatementToReturnStatement] Convert into 'return' statement" on /home/runner/work/Consolonia/Consolonia/src/Consolonia.Core/Drawing/BitmapImpl.cs(85,13)


[notice] 63-63:
"[ConvertToConstant.Local] Convert into constant" on /home/runner/work/Consolonia/Consolonia/src/Consolonia.Core/Drawing/BitmapImpl.cs(63,17)


[warning] 85-85:
"[RedundantTypeArgumentsOfMethod] Type argument specification is redundant" on /home/runner/work/Consolonia/Consolonia/src/Consolonia.Core/Drawing/BitmapImpl.cs(85,30)

🔇 Additional comments (7)
src/Consolonia.Core/Drawing/DrawingContextImpl.cs (2)

367-367: Clarify the commented transform check

The commented-out transform check suggests potential issues with non-translate transforms. This should either be implemented or removed with a clear explanation.

Please verify if non-translate transforms should be supported. If not, consider:

-//if (!Transform.IsTranslateOnly()) ConsoloniaPlatform.RaiseNotSupported(15);
+// TODO: Document why non-translate transforms are not supported
+if (!Transform.IsTranslateOnly())
+    throw new NotSupportedException("Only translate transforms are supported for text rendering");

63-77: 🛠️ Refactor suggestion

Consider using parallel processing for large bitmaps

The current pixel-by-pixel processing can be inefficient for large bitmaps. Using parallel processing could significantly improve performance.

Consider using parallel processing for the outer loop:

-for (int x = 0; x < width; x++)
-for (int y = 0; y < height; y++)
+Parallel.For(0, width, x =>
+{
+    for (int y = 0; y < height; y++)
     {
         int px = (int)targetRect.TopLeft.X + x;
         int py = (int)targetRect.TopLeft.Y + y;
         SKColor skColor = bitmap.GetPixel(x, y);
         Color color = Color.FromRgb(skColor.Red, skColor.Green, skColor.Blue);
         var imagePixel = new Pixel('█', color);
         CurrentClip.ExecuteWithClipping(new Point(px, py),
             () =>
             {
                 _pixelBuffer.Set(new PixelBufferCoordinate((ushort)px, (ushort)py),
                     (existingPixel, _) => existingPixel.Blend(imagePixel), imagePixel.Background.Color);
             });
     }
+});

Likely invalid or redundant comment.

src/Consolonia.Core/Drawing/BitmapImpl.cs (5)

24-28: Handle potential null SKBitmap after decoding from stream


30-33: Handle potential null SKBitmap after decoding from file


61-67: Allow format specification for stream-based Save method

🧰 Tools
🪛 GitHub Check: build

[notice] 63-63:
"[ConvertToConstant.Local] Convert into constant" on /home/runner/work/Consolonia/Consolonia/src/Consolonia.Core/Drawing/BitmapImpl.cs(63,17)


69-72: Implement the Lock method or handle its unavailability


39-39: Clarify scaling factor in PixelSize property

The PixelSize property scales Bitmap.Height by 0.55. Please verify whether this scaling factor is intentional, and consider adding a comment to explain its purpose.

src/Consolonia.Core/Drawing/BitmapImpl.cs Outdated Show resolved Hide resolved
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Outside diff range and nitpick comments (1)
src/Consolonia.Core/Drawing/BitmapImpl.cs (1)

40-40: Document the purpose of the 0.55 scaling factor.

The hardcoded scaling factor of 0.55 for height seems arbitrary. Consider:

  1. Adding a comment explaining its purpose
  2. Making it configurable if it's related to console character aspect ratio
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between e05d357 and 3dcecd3.

📒 Files selected for processing (1)
  • src/Consolonia.Core/Drawing/BitmapImpl.cs (1 hunks)
🧰 Additional context used
🪛 GitHub Check: build
src/Consolonia.Core/Drawing/BitmapImpl.cs

[warning] 86-86:
"[CA1308] In method 'GetFormatFromFileName', replace the call to 'ToLower' with 'ToUpperInvariant'" on /home/runner/work/Consolonia/Consolonia/src/Consolonia.Core/Drawing/BitmapImpl.cs(86,20)


[notice] 64-64:
"[ConvertToConstant.Local] Convert into constant" on /home/runner/work/Consolonia/Consolonia/src/Consolonia.Core/Drawing/BitmapImpl.cs(64,17)

src/Consolonia.Core/Drawing/BitmapImpl.cs Show resolved Hide resolved
src/Consolonia.Core/Drawing/BitmapImpl.cs Show resolved Hide resolved
src/Consolonia.Core/Drawing/BitmapImpl.cs Show resolved Hide resolved
src/Consolonia.Core/Drawing/BitmapImpl.cs Show resolved Hide resolved
src/Consolonia.Core/Drawing/BitmapImpl.cs Outdated Show resolved Hide resolved
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Outside diff range and nitpick comments (2)
src/Consolonia.Core/Drawing/BitmapImpl.cs (2)

2-2: Remove unused using directive.

The System.Globalization namespace is not used in the current implementation.

-using System.Globalization;
🧰 Tools
🪛 GitHub Check: build

[warning] 2-2:
"[RedundantUsingDirective] Using directive is not required by the code and can be safely removed" on /home/runner/work/Consolonia/Consolonia/src/Consolonia.Core/Drawing/BitmapImpl.cs(2,1)


38-38: Consider making DPI configurable.

The DPI is hardcoded to 96x96, which might not be suitable for all display scenarios. Consider making it configurable or detecting it from the system.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 3dcecd3 and 45f5f6d.

📒 Files selected for processing (1)
  • src/Consolonia.Core/Drawing/BitmapImpl.cs (1 hunks)
🧰 Additional context used
🪛 GitHub Check: build
src/Consolonia.Core/Drawing/BitmapImpl.cs

[notice] 64-64:
"[ConvertToConstant.Local] Convert into constant" on /home/runner/work/Consolonia/Consolonia/src/Consolonia.Core/Drawing/BitmapImpl.cs(64,17)


[warning] 2-2:
"[RedundantUsingDirective] Using directive is not required by the code and can be safely removed" on /home/runner/work/Consolonia/Consolonia/src/Consolonia.Core/Drawing/BitmapImpl.cs(2,1)

🔇 Additional comments (1)
src/Consolonia.Core/Drawing/BitmapImpl.cs (1)

40-40: Verify the height scaling factor.

The height scaling factor of 0.55 in the PixelSize property seems unusual and might affect bitmap display. This could lead to unexpected image distortion.

src/Consolonia.Core/Drawing/BitmapImpl.cs Show resolved Hide resolved
src/Consolonia.Core/Drawing/BitmapImpl.cs Show resolved Hide resolved
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Image drawing
3 participants